package GroupWare;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Vector;

import javax.swing.JLabel;

import Client.ClientListener;
import Client.MsgEvent;
import DBUtil.CNN;
import Server.ClientAcceptEvent;
import Server.ClientRequestEvent;
import Server.ServerListener;
import Tools.IMG;
import Tools.InfoFormat;
import Tools.Log;
import Tools.Units;
import Windows.MainWindows;
import Windows.ShowWindows.ShowWindow;
import XML.XML;
import XML.XMLNode;

/**
 * 共享目录类,提供文件搜索等功能
 * 
 * @author Administrator
 * 
 */
public class ShareRoot extends ShareFile implements ClientListener, ServerListener {
	public static void main(String[] args) throws IOException {
		byte[] b = new byte[] { (byte) 0xDE, (byte) 0xF6 };
		System.out.println(Arrays.toString(b));
		String str = toString(b);
		byte[] b2 = toBytes(str);
		System.out.println(Arrays.toString(b2));
//		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//		while (true) {
//			String line = br.readLine();
//			String regex = br.readLine();
//			String[] str = line.split(regex);
//			for (String var : str) {
//				System.out.println(">" + var);
//			}
//		}
	}
	public static byte[] toBytes(String data) {
		byte b[] = new byte[data.length() / 2];
		for (int i = 0; i < b.length; i++) {
			int n = Integer.parseInt(data.charAt(i * 2) + "" + data.charAt(i * 2 + 1), 16);
			b[i] = (byte) n;
		}
		return b;
	}
	public static String toString(byte[] b) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			sb.append(String.format("%02X", b[i]));
		}
		return sb.toString();
	}
	private XML DirDroit;// 目录权限配置

	private int bufsize = 100;// 缓存区大小
	private volatile LinkedList<ShareFile> alsf = new LinkedList<ShareFile>();// 缓存区
	private Thread workThread;
	// 提高取MD5文件速度
	private volatile LinkedList<ShareFile> alf = new LinkedList<ShareFile>();

	private boolean alter = true;// 通知同步线程刷新文件列表

	int Stype = 0;// 默认采用内存文件表

	ShowWindow sw;

	public ShareRoot(File path) {
		super(path);// 根目录文件
		DirDroit = new XML(new File("DirDroit.xml"));// 读取目录权限配置
		Log.print("[SharePath]" + DirDroit);

		try {
			// 读取搜索类型配置
			String str = (String) DBUtil.CNN.getConfig().GetPathValue("User.Share:seachtype");// 1
			// 表示物理搜索
			Stype = Integer.parseInt(str);
		} catch (Exception e) {
		}

		// 启动内存文件表刷新线程
		workThread = new Thread(new Runnable() {
			@Override
			public void run() {

				while (workThread == Thread.currentThread()) {
					while (alter) {// 收到刷新共享目录通知
						alter = false;
						Log.print("[SharePath]Update File List, Startting...");
						int count = setPath(getF());// 同步文件列表【同步线程】
						Log.print("[SharePath]Update File List, end... count:" + count);
						if (sw != null) {
							sw.getContentPane().add(new JLabel("刷新完毕...发现 " + count + " 个文件！"));
							sw.repaint();
							sw = null;
						}
					}
					Units.sleep(5000);
				}
				System.out.println("[SahreRoot]WorkThread Stop!");
			}
		});
		workThread.start();

		// alter = false;// 标记，否则物理搜索无效

	}

	@Override
	public void accepClientEvent(ClientAcceptEvent ace) {
	}

	/**
	 * 添加一个共享文件到缓存区
	 * 
	 * @param fd
	 */
	private void addBufferedFile(ShareFile fd) {
		synchronized (alsf) {
			int index = alsf.indexOf(fd);
			if (index == -1) {
				alsf.addFirst(fd);
			} else {
				alsf.addFirst(alsf.remove(index));
			}
			if (alsf.size() >= bufsize) {
				alsf.remove(alsf.size() - 1);// 将不常用的剔除
			}
		}
	}

	private void AddShareFile(File f) {
		for (int i = 0; i < alf.size(); i++) {
			if (alf.get(i).getF().equals(f)) {
				return;
			}
		}
		alf.add(new ShareFile(f));
	}

	/**
	 * 检查共享文件是否有效
	 * 
	 * @param sf
	 * @return
	 */
	private boolean checkFile(ShareFile sf) {
		boolean suc = false;
		suc = sf.getF().exists();
		if (!suc) {
			synchronized (alf) {
				alf.remove(sf);
			}
			synchronized (alsf) {
				alsf.remove(sf);
			}
		}
		return suc;
	}

	@Override
	public void ClientCloseEvent(Server.ClientExitEvent cce) {
	}

	@Override
	public void ClientException(Server.ClientException e) {

	}

	/**
	 * 取数字路径文件0,3 表示根目录下第0个目录下的第3个文件
	 * 
	 * @param als
	 * @return
	 */
	public File FileDir(ArrayList<Integer> als) {
		File f = getRootFile();// 取根目录
		try {
			for (int i = 0; i < als.size(); i++) {
				f = f.listFiles()[als.get(i)];// 取数字路径文件
			}
		} catch (Exception e) {
		}
		return f;
	}

	public int getCount() {
		return alf.size();
	}

	public String getDir() {
		return this.getF().getAbsolutePath();
	}

	/**
	 * 无权限获取文件列表，管理员使用
	 * 
	 * @param dir
	 * @return
	 */
	public XML getDirFiles(String dir) {
		XML flist = new XML();
		String path = this.getF().getAbsolutePath() + "\\" + dir;
		File f = new File(path);
		Log.print("[浏览目录]" + path + ",exists:" + f.exists());
		if (f.exists()) {
			for (int i = 0; i < alf.size(); i++) {
				ShareFile fi = alf.get(i);
				String flag = "FILE name='" + fi.getF().getName() + "'size='" + fi.getF().length() + "'time='" + fi.getF().lastModified() + "'md5='" + fi.md5 + "'";
				flist.add("", XML.parseFlag(null, flag), XML.BUTTOM);
			}
			return flist;
		} else
			return null;
	}

	/**
	 * 用户浏览文件列表
	 * 
	 * @param userID
	 *            欲浏览目录者
	 * @param dir
	 *            目录相对路径以\为前缀,在配置文件中是ID属性
	 * @return
	 */
	public XML getDirFiles(String userID, String dir) {
		boolean b = true;// 默认可读
		// --- 判断是否有可读权限
		XMLNode xf = (XMLNode) DirDroit.GetPathValue(MainWindows.getInstance().client.userid);
		if (xf != null) {// 判断是否已配置该用户，否则按照默认配置
			Vector<XMLNode> al = new Vector<XMLNode>();
			DirDroit.getList(al, xf, false);
			for (int i = 0; i < al.size(); i++) {
				xf = al.get(i);
				if (xf != null) {
					String dirs = xf.get("dir");
					if (dirs.equals(dir)) {
						b = Boolean.parseBoolean(xf.get("read"));
					}
				}
			}
		}
		XML xml = null;
		if (b)// 判断是否允许
			xml = getDirFiles(dir);
		return xml;
	}

	/**
	 * 取根目录文件
	 * 
	 * @return
	 */
	public File getRootFile() {
		return this.getF();
	}

	/**
	 * 通过MD5值获得文件对象
	 * 
	 * @param md5
	 * @return
	 */
	public ShareFile getShareFile(String md5) {
		ShareFile fd = null;
		boolean suc = false;
		boolean exists = false;
		// /////////查找缓存区/////////////
		synchronized (alsf) {
			for (int i = 0; i < alsf.size(); i++) {
				// 用缓存区可提高取文件速度
				ShareFile fdtmp = alsf.get(i);
				if (fdtmp.md5.equalsIgnoreCase(md5)) {
					exists = fdtmp.getF().exists();
					if (i > 0 && exists) {
						alsf.addFirst(alsf.remove(i));// 排在最前面
					}
					suc = true;
					fd = fdtmp;
					break;
				}
			}
		}
		// ////////////搜索文件表///////////////
		if (suc == false) {
			synchronized (alf) {
				for (int i = 0; i < alf.size(); i++) {
					ShareFile fdtmp = alf.get(i);
					if (fdtmp.md5.equalsIgnoreCase(md5)) {
						fd = fdtmp;
						exists = fd.getF().exists();
						addBufferedFile(fd);// 添加到缓存区
						break;
					}
				}
			}
		}
		// 检查文件有效性
		if (!exists && fd != null) {
			Log.print("[FileList]找到的文件不存在,记录将被删除。ShareFile: " + fd);
			synchronized (alf) {
				alf.remove(fd);
			}
			synchronized (alsf) {
				alsf.remove(fd);
			}
			fd = null;
		}
		return fd;
	}

	/**
	 * 查找文件表中是否存在指定的文件
	 * 
	 * @param f
	 * @return
	 */
	public int indexOf(File f) {
		for (int i = 0; i < alf.size(); i++) {
			ShareFile sf = alf.get(i);
			if (sf.f.equals(f)) {
				return i;
			}
		}
		return -1;
	}

	public boolean isAlter() {
		return alter;
	}

	@Override
	public void onCloseEvent(Client.CloseEvent cce) {

	}

	/**
	 * 【事件】服务端指指令事件
	 */
	@Override
	public void onMsgEvent(final MsgEvent ce) {
		XML cmd = ce.getCmd();

		String flg = cmd.FLAG;
		if (flg.equalsIgnoreCase("seach")) {// ---搜索文件请求
			new Thread(new Runnable() {

				// 启用线程来搜索（搜索时耗费时间，必须为独立的）防止其他指令等待
				@Override
				public void run() {
					if (Stype == 1 || alf == null || alf.size() == 0) {
						Log.print("[SearchRes]物理搜索开始...");
						searchPhysicFile(ce);// 物理模式搜索
						Log.print("[SearchRes]物理搜索结束...");
					} else {
						Log.print("[SearchRes]内存搜索开始...");
						seachFileTable(ce);// 虚拟模式搜索
						Log.print("[SearchRes]内存搜索结束...");
					}
				}
			}).start();

		} else if (flg.equalsIgnoreCase("get")) {// ---索取文件请求
			String md5 = cmd.get("md5");
			ShareFile fm = getShareFile(md5);

			if (fm != null) {
				// 获取文件种子
				Log.print("返回本机种子：" + md5);
				XML xml = new XML(cmd.toString());
				XMLNode xn = (XMLNode) xml.GetPathValue(cmd.FLAG);
				xn.FLAG = "pip";
				xn.put("size", String.valueOf(fm.getF().length()));
				xn.put("time", String.valueOf(fm.getF().lastModified()));
				xn.put("address", ce.getCs().getLocalAddress());
				xn.put("sport", String.valueOf(MainWindows.getInstance().client.fs.s.getLocalPort()));
				xn.setLeafage(true);
				ce.getCs().send(xml);
			} else {
				Log.print("Not found file-pip md5: " + md5);
			}
		} else if (flg.equalsIgnoreCase("dloadGet")) {// ---索取文件数据
			String md5 = cmd.get("md5");
			String offset = cmd.get("offset");
			String end = cmd.get("end");
			ShareFile fm = getShareFile(md5);

			if (fm != null) {
				// 服务器转发传输文件
				Log.print("请求本机种子数据：" + cmd);
				try {
					int offsetIndex = Integer.parseInt(offset);
					byte[] b = new byte[Integer.parseInt(end) - offsetIndex];
					RandomAccessFile raf = new RandomAccessFile(fm.getF(), "r");
					raf.seek(offsetIndex);
					for (int i = 0; i < b.length;) {
						int n = raf.read(b, i, b.length - i);
						if (n > 0) {
							i += n;
						}
					}
					raf.close();
					cmd.FLAG = "dloadData";
					cmd.setLeafage(false);
					cmd.setData(toString(b));
					cmd.clear();
					ce.getCs().send(cmd);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else if (flg.equalsIgnoreCase("dloadData")) {// ---收到种子数据
			String md5 = cmd.get("md5");
			String offset = cmd.get("offset");
			String end = cmd.get("end");
			String data = cmd.getData();

			Log.print("收到种子数据：" + md5 + "@" + offset + "-" + end + ": " + data.length());

			DownloadTask.dataRecv.put(md5 + ":" + offset + "-" + end, toBytes(data));

		} else if (flg.equalsIgnoreCase("lookfiles")) {// ---查看文件列表
			Log.print("[访问目录]" + cmd);
			String userID = cmd.get("userid");
			String dir = cmd.get("dir");
			XML flist = getDirFiles(userID, dir);// 取指定目录下的文件列表
			if (flist != null) {
				XML xml = new XML(cmd.toString());
				XMLNode xn = (XMLNode) xml.GetPathValue(cmd.FLAG);
				xn.FLAG = "dirlist";// 返回文件列表信息
				xml.add(xn, flist, XML.TOP);
				ce.getCs().send(xml);// 发送浏览文件列表
			}
		}
	}

	/**
	 * 移除某个共享文件
	 * 
	 * @param fd
	 */
	public boolean remove(ShareFile fd) {
		alf.remove(fd);
		return alf.remove(fd);
	}

	/**
	 * 【事件】客户监听端口接收到的请求
	 */
	@Override
	public void requestEvent(ClientRequestEvent se) {
		// 命令字符串转换到小写
		XML cmd = se.cmd;
		String flag = cmd.FLAG;
		if (flag.equalsIgnoreCase("get")) {// ---文件传输请求
			Log.print("[ShareDirectory]Request ResData,  " + cmd);
			String id = cmd.get("userid");// ---文件传输请求验证
			if (id == null || !id.equals(MainWindows.getInstance().client.userid))
				return;
			String md5 = cmd.get("md5");
			if (md5 == null) {
				Log.print("[种子返回]md5为空！");
				return;
			}
			RandomAccessFile raf = null;
			/*******************************************************************
			 * 查找共享文件
			 ******************************************************************/
			Log.print("[ShareDirectory]Send ResData,  " + cmd);
			ShareFile fd = getShareFile(md5);
			try {
				// 【线程安全】一个共享文件只允许队列形式输出资源，先来后到原则
				synchronized (fd) {
					raf = new RandomAccessFile(fd.getF(), "r");
					OutputStream dos = new DataOutputStream(new BufferedOutputStream(se.getCt().getSocket().getOutputStream()));
					long offset = Long.parseLong(cmd.get("offset"));//
					long end = Long.parseLong(cmd.get("end"));
					byte[] bt = new byte[ParcelBytes.getBuffer()];// 缓冲区
					int i = 0;
					long count = end - offset;// 当前需要读的总数
					se.getCt().getSocket().setSoTimeout(30000);// 超时时间30秒
					// Log.print("[transfers]Size:"+count+"\tStart:"+offset+"\tend"+end+"\t"+cmd);
					/***********************************************************
					 * 开始传输文件数据
					 **********************************************************/
					raf.seek(offset);// 设置指针开始位置
					while (count > 0 && (i = raf.read(bt)) != -1) {
						i = i <= count ? i : (int) count;
						dos.write(bt, 0, i);
						count -= i;
					}
					dos.flush();// 将剩余的缓冲字节输出
				}
			} catch (Exception e) {
				e.printStackTrace();
				Log.print("[资源服务]出现异常," + e.getMessage());
			} finally {
				try {
					raf.close();
				} catch (Exception e) {
				}
			}
		} else {
			Log.print("[未知指令]" + MainWindows.getInstance().client.getInetAddress() + " cmd:" + cmd);
		}
	}

	/**
	 * 搜索内存文件表,必须在独立的线程中执行，以免让其他任务等待 优点：搜索速度非常快，但如果目录文件更改频繁，将不确保搜索的准确性
	 * 
	 * @param keys
	 *            文件名关键字(通配符字符串：%[a-b]_)
	 * @param minSize
	 *            -1表示任意值
	 * @param maxSize
	 *            同上
	 * @return xml文件列表
	 */
	public void seachFileTable(MsgEvent ce) {
		XML cmd = ce.getCmd();
		String userid = cmd.get("userid");// 用户名
		String id = cmd.get("id");// 用户搜索标记
		if (id == null || userid == null) {
			Log.print("[ShareDirectory]search lost, request paramete error!");
			return;
		}
		// //////////////////////////////////
		String keys = cmd.get("keys").trim();
		keys = keys.replaceAll(" ++", "|");// 将空格转换成通配符%
		keys = keys.toLowerCase();// 不区分大小写

		// keys = "%" + keys + "%";
		// keys = keys.replaceAll("%_++", "%");
		// keys = keys.replaceAll("%++", "%");

		// /////////////////////////////////
		if (keys.equals("") || keys.equals("|")) {
			boolean b = false;
			try {
				b = Boolean.parseBoolean((String) CNN.getConfig().GetPathValue("User:searchempty"));// 判断是否允许搜索空
			} catch (Exception e) {
				Log.print(e);
			}
			if (!b)
				return;
		}

		Log.print("[SearchFile]regex:" + keys + "\trequest:" + cmd);

		String type = cmd.get("type");
		String min = cmd.get("minsize");
		String max = cmd.get("maxsize");

		int minSize = Integer.parseInt(min == null || min.equals("*") ? "-1" : min);
		int maxSize = Integer.parseInt(max == null || max.equals("*") ? "-1" : max);

		int count = 0;
		// /////////////////////////////////
		XML xml = new XML(cmd.toString());
		XMLNode xn = (XMLNode) xml.GetPathValue(cmd.FLAG);
		xn.put("keys", null);
		xn.put("minsize", null);
		xn.put("maxsize", null);
		xn.put("type", null);
		xn.put("sport", String.valueOf(MainWindows.getInstance().client.fs.getPort()));
		xn.FLAG = "sresult";

		// //////////////////////////////////
		for (int i = 0; i < alf.size(); i++) {
			if (alter) {
				Log.print("[SharePath]searchFile Stop! 共享目录改变，搜索中断！");
				return;// 目录已改变
			}
			ShareFile f = alf.get(i);
			String name = f.getF().getName();
			long leng = f.getF().length();

			name = name.toLowerCase();// 不区分大小写

			String[] str = name.split(keys);

			if (str.length > 1 && (minSize == -1 ? true : (leng >= minSize)) && (maxSize == -1 ? true : (leng <= maxSize)) && (type.equals("*") ? true : name.endsWith(type))) {
				if (checkFile(f)) {
					addBufferedFile(f);// 添加到缓存区,高速查找文件
					XMLNode x = XML.parseFlag(null, "FILE name=\"" + f.getF().getName() + "\"size=\"" + f.getF().length() + "\"time=\"" + f.getF().lastModified() + "\"md5=\"" + f.md5 + "\"");
					x.setLeafage(true);
					xml.add(xn, x, XML.BUTTOM);
					count++;
				}
			}
			if (count > 20 || i + 1 == alf.size()) {
				count = 0;
				ce.getCs().send(xml);// 发送搜索结果文件列表
				xml.remove(xn, true);
			}
		}
	}

	/**
	 * 物理文件搜索方法，非递归（优点：搜索结果准确无误，但文件太多会影响硬盘速度，导致系统极慢）
	 * 
	 * @param alf
	 * @param f
	 * @return
	 */
	public void searchPhysicFile(MsgEvent ce) {
		XML cmd = ce.getCmd();
		// =====提取搜索信息=======
		String userid = cmd.get("userid");// 用户名
		String id = cmd.get("id");// 用户搜索标记
		if (id == null || userid == null) {
			Log.print("[搜索文件]用户信息不明确!");
			return;
		}
		String keys = cmd.get("keys").replaceAll(" ++", "%");// 将空格转换成通配符%
		keys = "%" + keys + "%";
		keys = keys.replaceAll("%_++", "%");
		keys = keys.replaceAll("%++", "%");
		String type = cmd.get("type");
		String min = cmd.get("minsize");
		String max = cmd.get("maxsize");
		int minSize = Integer.parseInt(min == null || min.equals("*") ? "-1" : min);
		int maxSize = Integer.parseInt(max == null || min.equals("*") ? "-1" : max);

		// /////////////////////////////////
		XML xml = new XML(cmd.toString());
		XMLNode xn = (XMLNode) xml.GetPathValue(cmd.FLAG);
		xn.FLAG = "sresult";
		xn.take("keys");
		xn.take("minsize");
		xn.take("maxsize");
		xn.take("type");
		xn.put("sport", String.valueOf(MainWindows.getInstance().client.fs.getPort()));
		// //////////////////////////////////

		// =======初始化======
		String res;
		int scount = 0;// 以查找文件数
		int count = 0;// 统计搜索结果数量
		boolean backdate = false;// 回溯标记
		ArrayList<Integer> als = new ArrayList<Integer>();// 栈
		als.add(Integer.valueOf(0));// 根目录第一个文件入栈

		// =======开始搜索遍历======
		while (als.size() > 0) {
			if (alter) {// 收到目录切换通知，结束搜索
				Log.print("[搜索结束]共享目录被改变, " + cmd);
				return;
			}

			int stackTop = als.size() - 1;// 获取栈顶
			File f = FileDir(als);
			if (f == getRootFile() || f == null) {
				Log.print("[搜索结束] 回溯到根目录，" + cmd);
				return;// 回溯结束
			}
			if (f.isFile()) {
				scount++;// 统计搜索文件数
				// =======通配搜索处理============
				try {
					String name = f.getName();
					long leng = f.length();
					if (XML.like(keys, name) && (minSize == -1 ? true : (leng >= minSize)) && (maxSize == -1 ? true : (leng <= maxSize)) && (type.equals("*") ? true : name.endsWith(type))) {

						// addBufferedFile((f));//添加到缓存区
						XMLNode x = XML.parseFlag(null, "FILE name=\"" + name + "\"size=\"" + leng + "\"time=\"" + f.lastModified() + "\"md5=\"" + InfoFormat.FileMD5(f) + "\"/");
						x.setLeafage(true);
						xml.add(xn, x, XML.BUTTOM);
						count++;

						AddShareFile(f);// 找到后加入到表中,对方用户下载需要在虚拟表中查找MD5文件

					}
					if (count > 20 || (scount % 100 == 0 && count > 0)) {// 流模式返回搜索结果
						// ：
						// 20
						// 个为一组或搜索超过100个文件将返回一次
						count = 0;
						ce.getCs().send(xml);
						xml.remove(xn, true);
					}
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					// =======文件列表游标下移一个单位========
					int k = als.get(stackTop) + 1;
					if (k < f.getParentFile().listFiles().length) {
						als.set(stackTop, Integer.valueOf(k));// 扫描下一个文件
						// Log.print("[next]"+als);
					} else {// 当前目录文件列表游标到顶
						als.remove(stackTop);// 出栈回溯
						backdate = true;// 标记回溯
						// Log.print("[Down]"+als);
					}
				}
			} else if (f.isDirectory()) {
				// Log.print("[搜索目录]"+f);
				if (backdate) {
					backdate = false;
					int k = als.get(stackTop) + 1;// 取回溯目录游标下移

					if (k >= f.getParentFile().listFiles().length) {
						als.remove(stackTop);// 游标超出范围，回溯
						backdate = true;
					} else {
						als.set(stackTop, Integer.valueOf(k));// 扫描下一个文件
					}
				} else {
					File[] ftmp = f.listFiles();
					if (ftmp != null && ftmp.length > 0) {// 目录不为空：第一个文件入栈
						als.add(Integer.valueOf(0));
						// Log.print("[upTop]"+als);
					} else {
						// 文件夹为空继续下一个同级文件
						int k = als.get(stackTop) + 1;// 取回溯目录游标下移
						if (k >= f.getParentFile().listFiles().length) {
							als.remove(stackTop);// 游标超出范围，回溯
							backdate = true;
						} else {
							als.set(stackTop, Integer.valueOf(k));// 扫描下一个文件
						}
					}
				}
			} else {
				als.remove(stackTop);// 未知文件，继续回溯
				backdate = true;
				// Log.print("[?Down]"+als);
			}

		}
		Log.print("[搜索结束]" + cmd);

		if (count > 0) {// 数据不为空，发送遗留数据
			count = 0;
			ce.getCs().send(xml);
		}
	}

	/**
	 * 通知工作线程更新共享目录
	 * 
	 * @param alter
	 */
	public void setAlter(boolean alter) {
		this.alter = alter;
		sw = new ShowWindow(IMG.share);
		sw.getContentPane().add(new JLabel("提示：刷新共享目录文件列表..."));
		sw.start();
	}

	@Override
	public void setF(File f) {
		alter = f != null && !this.f.equals(f);// 检查是否需要更新
		if (alter) {
			this.f = f;
			updateFileList();
			MainWindows.Tree.jTree.updateUI();
		}
	}

	/**
	 * 目录共享文件遍历(递归算法)
	 * 
	 * @param alf
	 * @param f
	 * @return
	 */
	public int setFileMd5(LinkedList<ShareFile> alf, File f) {
		int k = 0;
		if (f.isDirectory()) {
			File[] fs = f.listFiles();
			if (fs != null)
				for (int i = 0; i < fs.length; i++) {
					if (alter) {// 收到目录切换通知
						return k;
					}
					if (fs[i].isFile()) {
						ShareFile fd = new ShareFile(fs[i]);
						alf.add(fd);
						k++;
					}
					if (fs[i].isDirectory()) {
						k += setFileMd5(alf, fs[i]);// 递归--枚举子文件夹
					}
				}
		}
		return k;
	}

	/**
	 * 设置共享目录,请不要在主线程中调用，以免出现假死现象
	 * 
	 * @param f
	 *            目录文件
	 * @return
	 */
	public int setPath(File f) {
		this.setF(f);
		LinkedList<ShareFile> alf = new LinkedList<ShareFile>();
		int i = setFileMd5(alf, f);// 获取文件
		this.alf = alf;
		return i;
	}

	@Override
	public String toString() {
		return "共享目录";
	}
}
